Skip to content

test: automated testing prototype — pytest infrastructure + unit tests for 5 integrations#250

Merged
TheRealAgentK merged 22 commits intomasterfrom
test/automated-testing-prototype
Apr 20, 2026
Merged

test: automated testing prototype — pytest infrastructure + unit tests for 5 integrations#250
TheRealAgentK merged 22 commits intomasterfrom
test/automated-testing-prototype

Conversation

@TheRealAgentK
Copy link
Copy Markdown
Collaborator

@TheRealAgentK TheRealAgentK commented Apr 16, 2026

This PR introduces automated testing infrastructure for Autohive integrations, including pytest configuration, unit tests for 6 integrations, and end-to-end integration tests for 3 of those.


What's in this PR

1. Pytest Infrastructure

File Purpose
pyproject.toml pytest config: asyncio_mode=auto, python_files=test_*_unit.py, -m unit default, coverage settings
conftest.py (root) Monkeypatches Integration.load() for test discovery + stdlib .env loader
requirements-test.txt pytest, pytest-asyncio, pytest-cov — no SDK (each integration provides its own)
.env.example Template for integration test credentials (gitignored local .env holds actual values)
.gitignore Added .env

2. Unit Tests (206 tests, all CI-safe)

Mocked tests that run without credentials or network access. Auto-discovered by pytest via test_*_unit.py naming.

Integration Tests Coverage Areas
hackernews 29 All 8 actions, helpers (format_item, format_comment), error handling, edge cases
bitly 37 All 12 actions, helpers (normalize_bitlink, encode_bitlink), pagination, error handling
nzbn 41 All 10 actions, OAuth token caching, credential validation, pagination, error handling
notion 31 14 actions (search, CRUD pages/blocks/comments, data sources), error handling
shopify-customer 31 8 of 12 actions, helpers, OAuth URL building, PKCE, GraphQL error handling
perplexity 29 search_web action, parse_response helper, API key handling, rate limiting, all error paths

Total: 198 unit tests (auto-discovered by CI)

Note: shopify-customer has known output schema bugs — error paths return None for fields declared as type: "object". SDK 1.0.2 raises ValidationError; tests use pytest.raises(ValidationError). 4 actions (update_profile, update_address, delete_address, refresh_token) lack mocked test coverage.

3. Integration Tests (32 e2e tests, never run in CI)

End-to-end tests that call real APIs. Excluded from CI by two mechanisms:

  1. python_files restricts auto-discovery to test_*_unit.py
  2. addopts includes -m unit, which deselects @pytest.mark.integration tests

Tests skip gracefully via pytest.skip() if required credentials are not set.

Integration Tests Auth Notes
hackernews 12 None (public API) All 8 actions, story/comment structure validation, user profile
bitly 10 BITLY_ACCESS_TOKEN 9 read-only actions; write actions excluded. 4 tests require ≥1 bitlink in account
perplexity 10 PERPLEXITY_API_KEY search_web with all parameter combinations, result structure, cost validation

Total: 32 integration tests (local-only, credential-gated)

Run locally:

pytest hackernews/tests/test_hackernews_integration.py -m integration
pytest bitly/tests/test_bitly_integration.py -m integration
pytest perplexity/tests/test_perplexity_integration.py -m integration

4. Perplexity Integration (new)

Ported from the private Autohive-AI/integrations repo with security cleanup:

  • Replaced hardcoded API key with os.environ.get("PERPLEXITY_API_KEY") + error handling
  • Updated README, bumped version to 1.1.0
  • Added entry to main README.md

5. Legacy Test Cleanup

Removed old manual test runners (asyncio.run(main()) scripts) and their context.py files for integrations that now have proper pytest coverage:

Integration Removed Replaced by
hackernews test_hackernews.py, context.py test_hackernews_unit.py (29) + test_hackernews_integration.py (12)
bitly test_bitly.py, context.py test_bitly_unit.py (37) + test_bitly_integration.py (10)
perplexity test_perplexity.py, context.py test_perplexity_unit.py (29) + test_perplexity_integration.py (10)

nzbn, notion, and shopify-customer still have their legacy test files (removal pending).

6. Documentation

  • CONTRIBUTING.md: New "Running Tests" section with comparison table, correct commands for both test types, templates for writing unit and integration tests
  • pyproject.toml: Comments explaining python_files restriction and how to run integration tests
  • TEST_STOCKTAKE.md: Audit of all 86 integrations' test coverage, patterns, and gaps

7. CI-related fixes

  • Lint/format fixes for ruff compliance (tooling's ruff.toml, line-length=120)
  • bandit security fixes (nosec annotations where appropriate)
  • Patch bumps for bitly, notion, nzbn to 1.0.1 (ruff format changed their source files)

Test Architecture

pytest (default)                    pytest <file> -m integration
    │                                       │
    ▼                                       ▼
python_files: test_*_unit.py        Explicit file path bypasses
addopts: -m unit                    python_files restriction
    │                               -m integration overrides addopts
    ▼                                       │
CI-safe mocked tests                        ▼
No credentials needed               Real API calls
Auto-discovered                      Credentials from .env
                                     Skip if env var missing

Key Design Decisions

  • No SDK in requirements-test.txt: Each integration pins its own SDK version in requirements.txt. The CI test runner (run_tests.py in tooling) installs deps per-integration to respect version pins.
  • python_files = ["test_*_unit.py"]: Integration tests are excluded from discovery at the file level, not just the marker level. This prevents accidental CI execution even if someone forgets the marker.
  • Double exclusion for integration tests: File naming (test_*_integration.py not matched by python_files) AND marker (-m unit in addopts deselects @pytest.mark.integration). Belt and suspenders.
  • Integration.load() monkeypatch: The SDK resolves config.json relative to its own package location, which breaks when installed as a site-package. The root conftest.py monkeypatches it to use frame inspection. A proper fix (passing explicit paths) is documented in TEST_STOCKTAKE.md.

Tooling Repo Changes (separate PRs)

This work was supported by changes to autohive-integrations-tooling:

PR Description Status
#27 Added pytest CI step (run_tests.py, action.yml updates) ✅ Merged
#28 Skip version bump for test/doc-only changes ✅ Merged
#29 Per-integration dep install in run_tests.py ✅ Merged
#34 Skip version bump for formatting-only changes (git diff -w) ✅ Merged
#35 run_tests.py documentation ✅ Merged
#36 Accept conftest.py as alternative to context.py in validation, document unit/integration test separation 🔄 Open

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 16, 2026

🔍 Integration Validation Results

Commit: 00ed5d7ebb2672a244f16c9b89e9f8c6fa84b83a · ci: retrigger CI with tooling 2.0.6
Updated: 2026-04-20T02:36:27Z

Changed directories: bitly hackernews notion nzbn perplexity shopify-customer

Check Result
Structure ⚠️ Passed with warnings
Code ⚠️ Passed with warnings
Tests ✅ Passed
README ✅ Passed
Version ⚠️ Passed with warnings
⚠️ Structure Check output
Validating 6 integration(s)...

============================================================
Integration: bitly
============================================================

Warnings (1):
  ⚠️ SDK version 1.0.2 is deprecated — upgrade to autohive-integrations-sdk~=1.1.1 or later

============================================================
Integration: hackernews
============================================================

Warnings (1):
  ⚠️ SDK version 1.0.2 is deprecated — upgrade to autohive-integrations-sdk~=1.1.1 or later

============================================================
Integration: notion
============================================================

Warnings (1):
  ⚠️ SDK version 1.0.2 is deprecated — upgrade to autohive-integrations-sdk~=1.1.1 or later

============================================================
Integration: nzbn
============================================================

Warnings (1):
  ⚠️ SDK version 1.0.2 is deprecated — upgrade to autohive-integrations-sdk~=1.1.1 or later

============================================================
Integration: perplexity
============================================================

Warnings (1):
  ⚠️ SDK version 1.0.2 is deprecated — upgrade to autohive-integrations-sdk~=1.1.1 or later

============================================================
Integration: shopify-customer
============================================================

Warnings (2):
  ⚠️ Unknown auth type: 'oauth2_pkce'. Expected 'platform' or 'custom'
  ⚠️ SDK version 1.0.2 is deprecated — upgrade to autohive-integrations-sdk~=1.1.1 or later

============================================================
SUMMARY
============================================================
Integrations validated: 6
Total errors: 0
Total warnings: 7

⚠️ Validation passed with warnings - please review
⚠️ Code Check output
----------------------------------------
Checking: bitly
----------------------------------------

📦 Installing dependencies...

🐍 Checking Python syntax...
   ✅ Syntax OK

📥 Checking imports...
   ✅ Imports OK

📄 Checking JSON files...
   ✅ JSON files OK

🔍 Linting with ruff...
   ✅ Lint OK

🎨 Checking formatting with ruff...
   ✅ Formatting OK

🔒 Scanning for security issues with bandit...
   ✅ Security OK

🛡️ Checking dependencies for vulnerabilities with pip-audit...
   ✅ Dependencies OK

🔗 Checking config-code sync...
   ✅ Config-code sync OK

🔄 Checking fetch patterns...
   ✅ Fetch patterns OK

----------------------------------------
Checking: hackernews
----------------------------------------

📦 Installing dependencies...

🐍 Checking Python syntax...
   ✅ Syntax OK

📥 Checking imports...
   ✅ Imports OK

📄 Checking JSON files...
   ✅ JSON files OK

🔍 Linting with ruff...
   ✅ Lint OK

🎨 Checking formatting with ruff...
   ✅ Formatting OK

🔒 Scanning for security issues with bandit...
   ✅ Security OK

🛡️ Checking dependencies for vulnerabilities with pip-audit...
   ✅ Dependencies OK

🔗 Checking config-code sync...
   ✅ Config-code sync OK

🔄 Checking fetch patterns...
   ✅ Fetch patterns OK

----------------------------------------
Checking: notion
----------------------------------------

📦 Installing dependencies...

🐍 Checking Python syntax...
   ✅ Syntax OK

📥 Checking imports...
   ✅ Imports OK

📄 Checking JSON files...
   ✅ JSON files OK

🔍 Linting with ruff...
   ✅ Lint OK

🎨 Checking formatting with ruff...
   ✅ Formatting OK

🔒 Scanning for security issues with bandit...
   ✅ Security OK

🛡️ Checking dependencies for vulnerabilities with pip-audit...
   ✅ Dependencies OK

🔗 Checking config-code sync...
   ⚠️  Action 'search_notion': parameter 'start_cursor' is optional in schema but accessed with inputs["start_cursor"] (will raise KeyError if not provided)
   ⚠️  Action 'search_notion': parameter 'filter' is optional in schema but accessed with inputs["filter"] (will raise KeyError if not provided)
   ⚠️  Action 'search_notion': parameter 'page_size' is optional in schema but accessed with inputs["page_size"] (will raise KeyError if not provided)
   ⚠️  Action 'search_notion': parameter 'sort' is optional in schema but accessed with inputs["sort"] (will raise KeyError if not provided)
   ⚠️  Action 'get_notion_comments': parameter 'start_cursor' is optional in schema but accessed with inputs["start_cursor"] (will raise KeyError if not provided)
   ⚠️  Action 'get_notion_comments': parameter 'page_size' is optional in schema but accessed with inputs["page_size"] (will raise KeyError if not provided)
   ⚠️  Action 'list_data_sources': parameter 'start_cursor' is optional in schema but accessed with inputs["start_cursor"] (will raise KeyError if not provided)
   ⚠️  Action 'list_data_sources': parameter 'page_size' is optional in schema but accessed with inputs["page_size"] (will raise KeyError if not provided)
   ⚠️  Action 'query_notion_data_source': parameter 'start_cursor' is optional in schema but accessed with inputs["start_cursor"] (will raise KeyError if not provided)
   ⚠️  Action 'query_notion_data_source': parameter 'filter' is optional in schema but accessed with inputs["filter"] (will raise KeyError if not provided)
   ⚠️  Action 'query_notion_data_source': parameter 'sorts' is optional in schema but accessed with inputs["sorts"] (will raise KeyError if not provided)
   ⚠️  Action 'query_notion_data_source': parameter 'page_size' is optional in schema but accessed with inputs["page_size"] (will raise KeyError if not provided)
   ⚠️  Action 'get_notion_block_children': parameter 'start_cursor' is optional in schema but accessed with inputs["start_cursor"] (will raise KeyError if not provided)
   ⚠️  Action 'get_notion_block_children': parameter 'page_size' is optional in schema but accessed with inputs["page_size"] (will raise KeyError if not provided)
   ⚠️  Action 'append_notion_block_children': parameter 'after' is optional in schema but accessed with inputs["after"] (will raise KeyError if not provided)
   ⚠️  Action 'get_notion_page_property': parameter 'start_cursor' is optional in schema but accessed with inputs["start_cursor"] (will raise KeyError if not provided)
   ⚠️  Action 'get_notion_page_property': parameter 'page_size' is optional in schema but accessed with inputs["page_size"] (will raise KeyError if not provided)
   ⚠️  Action 'update_notion_block': parameter 'quote' defined in input_schema but never accessed in code
   ⚠️  Action 'update_notion_block': parameter 'heading_1' defined in input_schema but never accessed in code
   ⚠️  Action 'update_notion_block': parameter 'paragraph' defined in input_schema but never accessed in code
   ⚠️  Action 'update_notion_block': parameter 'bulleted_list_item' defined in input_schema but never accessed in code
   ⚠️  Action 'update_notion_block': parameter 'numbered_list_item' defined in input_schema but never accessed in code
   ⚠️  Action 'update_notion_block': parameter 'code' defined in input_schema but never accessed in code
   ⚠️  Action 'update_notion_block': parameter 'heading_3' defined in input_schema but never accessed in code
   ⚠️  Action 'update_notion_block': parameter 'to_do' defined in input_schema but never accessed in code
   ⚠️  Action 'update_notion_block': parameter 'heading_2' defined in input_schema but never accessed in code
   ⚠️  Action 'update_notion_page': parameter 'properties' defined in input_schema but never accessed in code
   ⚠️  Action 'update_notion_page': parameter 'cover' defined in input_schema but never accessed in code
   ⚠️  Action 'update_notion_page': parameter 'icon' defined in input_schema but never accessed in code
   ⚠️  Action 'update_notion_page': parameter 'archived' defined in input_schema but never accessed in code
   ✅ Config-code sync OK

🔄 Checking fetch patterns...
   ✅ Fetch patterns OK

----------------------------------------
Checking: nzbn
----------------------------------------

📦 Installing dependencies...

🐍 Checking Python syntax...
   ✅ Syntax OK

📥 Checking imports...
   ✅ Imports OK

📄 Checking JSON files...
   ✅ JSON files OK

🔍 Linting with ruff...
   ✅ Lint OK

🎨 Checking formatting with ruff...
   ✅ Formatting OK

🔒 Scanning for security issues with bandit...
   ✅ Security OK

🛡️ Checking dependencies for vulnerabilities with pip-audit...
   ✅ Dependencies OK

🔗 Checking config-code sync...
   ⚠️  Action 'search_entities': parameter 'search_term' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️  Action 'get_entity': parameter 'nzbn' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️  Action 'get_entity_summary': parameter 'nzbn' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️  Action 'get_entity_addresses': parameter 'nzbn' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️  Action 'get_entity_roles': parameter 'nzbn' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️  Action 'get_entity_trading_names': parameter 'nzbn' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️  Action 'get_company_details': parameter 'nzbn' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️  Action 'get_entity_gst_numbers': parameter 'nzbn' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️  Action 'get_entity_industry_classifications': parameter 'nzbn' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️  Action 'get_changes': parameter 'change_event_type' is required in schema but accessed with inputs.get() (safe for missing)
   ✅ Config-code sync OK

🔄 Checking fetch patterns...
   ✅ Fetch patterns OK

----------------------------------------
Checking: perplexity
----------------------------------------

📦 Installing dependencies...

🐍 Checking Python syntax...
   ✅ Syntax OK

📥 Checking imports...
   ✅ Imports OK

📄 Checking JSON files...
   ✅ JSON files OK

🔍 Linting with ruff...
   ✅ Lint OK

🎨 Checking formatting with ruff...
   ✅ Formatting OK

🔒 Scanning for security issues with bandit...
   ✅ Security OK

🛡️ Checking dependencies for vulnerabilities with pip-audit...
   ✅ Dependencies OK

🔗 Checking config-code sync...
   ⚠️  Action 'search_web': parameter 'country' is optional in schema but accessed with inputs["country"] (will raise KeyError if not provided)
   ⚠️  Action 'search_web': parameter 'content_depth' is optional in schema but accessed with inputs["content_depth"] (will raise KeyError if not provided)
   ⚠️  Action 'search_web': parameter 'max_results' is optional in schema but accessed with inputs["max_results"] (will raise KeyError if not provided)
   ✅ Config-code sync OK

🔄 Checking fetch patterns...
   ✅ Fetch patterns OK

----------------------------------------
Checking: shopify-customer
----------------------------------------

📦 Installing dependencies...

🐍 Checking Python syntax...
   ✅ Syntax OK

📥 Checking imports...
   ✅ Imports OK

📄 Checking JSON files...
   ✅ JSON files OK

🔍 Linting with ruff...
   ✅ Lint OK

🎨 Checking formatting with ruff...
   ✅ Formatting OK

🔒 Scanning for security issues with bandit...
   ✅ Security OK

🛡️ Checking dependencies for vulnerabilities with pip-audit...
   ✅ Dependencies OK

🔗 Checking config-code sync...
   ⚠️  Action 'customer_update_profile': parameter 'last_name' defined in input_schema but never accessed in code
   ⚠️  Action 'customer_update_profile': parameter 'accepts_marketing' defined in input_schema but never accessed in code
   ⚠️  Action 'customer_update_profile': parameter 'phone' defined in input_schema but never accessed in code
   ⚠️  Action 'customer_update_profile': parameter 'first_name' defined in input_schema but never accessed in code
   ⚠️  Action 'customer_create_address': parameter 'address1' defined in input_schema but never accessed in code
   ⚠️  Action 'customer_create_address': parameter 'phone' defined in input_schema but never accessed in code
   ⚠️  Action 'customer_create_address': parameter 'first_name' defined in input_schema but never accessed in code
   ⚠️  Action 'customer_create_address': parameter 'province' defined in input_schema but never accessed in code
   ⚠️  Action 'customer_create_address': parameter 'city' defined in input_schema but never accessed in code
   ⚠️  Action 'customer_create_address': parameter 'address2' defined in input_schema but never accessed in code
   ⚠️  Action 'customer_create_address': parameter 'zip' defined in input_schema but never accessed in code
   ⚠️  Action 'customer_create_address': parameter 'country' defined in input_schema but never accessed in code
   ⚠️  Action 'customer_create_address': parameter 'company' defined in input_schema but never accessed in code
   ⚠️  Action 'customer_create_address': parameter 'last_name' defined in input_schema but never accessed in code
   ⚠️  Action 'customer_update_address': parameter 'address1' defined in input_schema but never accessed in code
   ⚠️  Action 'customer_update_address': parameter 'phone' defined in input_schema but never accessed in code
   ⚠️  Action 'customer_update_address': parameter 'first_name' defined in input_schema but never accessed in code
   ⚠️  Action 'customer_update_address': parameter 'province' defined in input_schema but never accessed in code
   ⚠️  Action 'customer_update_address': parameter 'city' defined in input_schema but never accessed in code
   ⚠️  Action 'customer_update_address': parameter 'address2' defined in input_schema but never accessed in code
   ⚠️  Action 'customer_update_address': parameter 'zip' defined in input_schema but never accessed in code
   ⚠️  Action 'customer_update_address': parameter 'country' defined in input_schema but never accessed in code
   ⚠️  Action 'customer_update_address': parameter 'company' defined in input_schema but never accessed in code
   ⚠️  Action 'customer_update_address': parameter 'last_name' defined in input_schema but never accessed in code
   ⚠️  Action 'customer_update_address': parameter 'address_id' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️  Action 'customer_delete_address': parameter 'address_id' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️  Action 'customer_set_default_address': parameter 'address_id' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️  Action 'customer_get_order': parameter 'order_id' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️  Action 'customer_generate_oauth_url': parameter 'redirect_uri' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️  Action 'customer_generate_oauth_url': parameter 'client_id' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️  Action 'customer_exchange_code': parameter 'code' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️  Action 'customer_exchange_code': parameter 'code_verifier' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️  Action 'customer_exchange_code': parameter 'client_id' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️  Action 'customer_exchange_code': parameter 'redirect_uri' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️  Action 'customer_refresh_token': parameter 'client_id' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️  Action 'customer_refresh_token': parameter 'refresh_token' is required in schema but accessed with inputs.get() (safe for missing)
   ✅ Config-code sync OK

🔄 Checking fetch patterns...
   ✅ Fetch patterns OK

========================================
✅ CODE CHECK PASSED
========================================
✅ Tests output

Integration          Tests  Coverage        Status
--------------------------------------------------
bitly                37/37       92%      ✅ Passed
hackernews           29/29       89%      ✅ Passed
notion               39/39       67%      ✅ Passed
nzbn                 41/41       76%      ✅ Passed
perplexity           29/29       98%      ✅ Passed
shopify-customer     31/31       61%      ✅ Passed
--------------------------------------------------
Total              206/206            ✅ All passed

✅ Tests passed: bitly, hackernews, notion, nzbn, perplexity, shopify-customer
✅ README Check output
========================================
✅ README CHECK PASSED
========================================
⚠️ Version Check output
✅ bitly: 1.0.0 → 1.0.1 (patch bump) (⚠️ consider a minor bump — new features detected (new functions, classes, or actions))
✅ hackernews: No version bump needed (only tests/docs changed)
✅ notion: 1.0.0 → 1.0.1 (patch bump) (⚠️ consider a minor bump — new features detected (new functions, classes, or actions))
✅ nzbn: 1.0.0 → 1.0.1 (patch bump) (⚠️ consider a minor bump — new features detected (new functions, classes, or actions))
✅ perplexity: New integration with version 1.1.0
✅ shopify-customer: No version bump needed (only tests/docs changed)

========================================
✅ VERSION CHECK PASSED
========================================

@TheRealAgentK TheRealAgentK force-pushed the test/automated-testing-prototype branch from 71ddc0b to ef9aa11 Compare April 16, 2026 01:41
Comment thread bitly/tests/test_bitly_unit.py Fixed
Comment thread nzbn/tests/test_nzbn_unit.py Fixed
Comment thread hackernews/tests/test_hackernews_unit.py Fixed
Comment thread shopify-customer/tests/test_shopify_customer_unit.py Fixed
Comment thread shopify-customer/tests/test_shopify_customer_unit.py Fixed
@TheRealAgentK TheRealAgentK force-pushed the test/automated-testing-prototype branch from 27c8bf9 to 9cf3eb0 Compare April 16, 2026 02:32
TheRealAgentK and others added 11 commits April 16, 2026 15:38
- Add pytest/coverage config (pyproject.toml, requirements-test.txt)
- Add root conftest.py with shared fixtures and Integration.load() patch
- Add .env.example for integration test credentials
- Add unit tests for hackernews (29), bitly (37), nzbn (41), notion (39), shopify-customer (31)
- Update CONTRIBUTING.md with test setup, running, and coverage docs
- Add TEST_STOCKTAKE.md with full audit of existing test landscape

All 177 tests pass with zero credentials required.
Coverage: bitly 92%, hackernews 89%, nzbn 76%, notion 67%, shopify-customer 60%.
- Remove unused variable assignments (F841)
- Add nosec B105 for test credential strings
- Add noqa E402 for imports after sys.path.insert
- Remove unused imports (F401)
- Apply ruff format
CI runs ruff with the tooling's ruff.toml config which uses line-length=120.
Previous format commit used the default line-length=88, causing mismatches.
This reformats all files in the 5 integration directories plus conftest.py
using the correct config.
…rror tests

The SDK may either raise ValidationError (output schema validation) or
return a result with error indicators, depending on the installed version.
Added _expect_validation_error() helper that accepts both behaviors.
…alidation errors

Pin autohive-integrations-sdk~=1.0.2 in requirements-test.txt to match
what shopify-customer (and all other integrations) actually use.

SDK 1.0.2 raises ValidationError on output schema mismatches without
catching it internally, so tests must use pytest.raises(ValidationError).
Removed the _expect_validation_error helper that masked this.
…idation

SDK version is owned by each integration's requirements.txt, not the
test infrastructure. The tooling's run_tests.py now installs deps
per-integration. Tests use pytest.raises(ValidationError) which matches
SDK 1.0.2 behavior (raises instead of catching internally).
@TheRealAgentK TheRealAgentK force-pushed the test/automated-testing-prototype branch from cd5c812 to b972487 Compare April 16, 2026 03:39
…eanup

Ported the Perplexity search integration from the private integrations
repo. Replaced hardcoded API key with PERPLEXITY_API_KEY environment
variable lookup. Returns a clear error message if the env var is not
set or empty. Updated README and error messages to reference the env
var. No secrets committed.

Version bumped to 1.1.0 (minor) for the auth change.
- 29 mocked unit tests for search_web action (all passing)
- 10 e2e integration tests (skip if PERPLEXITY_API_KEY not set)
- tests/conftest.py for sys.path setup
- .env.example updated with PERPLEXITY_API_KEY placeholder
Superseded by test_perplexity_unit.py (29 mocked tests) and
test_perplexity_integration.py (10 e2e tests). All 8 original
scenarios are covered plus 20 additional cases.
- 12 e2e tests covering all 8 actions against the live HN API
- No credentials needed (public API)
- Removes test_hackernews.py (manual asyncio.run runner) and context.py
- 10 e2e tests covering all 9 read-only actions against the live Bitly API
- Skip if BITLY_ACCESS_TOKEN not set; 4 tests also skip if no bitlinks exist
- Write actions (shorten_url, create_bitlink, update_bitlink) excluded
- Removes test_bitly.py (manual asyncio.run runner) and context.py
…d pyproject.toml

- Add comparison table showing file naming, markers, discovery, and CI behavior
- Fix incorrect integration test command (pytest -m integration dir/ doesn't work)
- Add integration test template and writing guide
- Add clarifying comments to pyproject.toml
@TheRealAgentK TheRealAgentK marked this pull request as ready for review April 20, 2026 01:59
@TheRealAgentK
Copy link
Copy Markdown
Collaborator Author

TheRealAgentK commented Apr 20, 2026

Note: The structural test failures in this PR are currently expected and will go away with the next tooling bump (already PR'ed)

Errors (1):
❌ Missing tests/context.py (Test context/import setup)

@TheRealAgentK TheRealAgentK merged commit efe2332 into master Apr 20, 2026
3 checks passed
@TheRealAgentK TheRealAgentK deleted the test/automated-testing-prototype branch April 20, 2026 22:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants